#include "jsapi.h"
#include "js-engine.h"
#include "desktopClasses.h"
#include "basicElementClass.h"
#include "mainview-parser.h"

static JSBool edit_new(JSContext *cx, JSObject *obj, uintN argc, jsval *args, jsval *rval);
static JSBool edit_SetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);

extern JSBool basicElement_SetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);

struct JSFunctionSpec edit_methods[] = {
    {NULL, NULL}
};

JSClass editClass =
    { "edit", JSCLASS_HAS_PRIVATE,
      JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, edit_SetProperty,
      JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
      JSCLASS_NO_OPTIONAL_MEMBERS
    };

struct property_parser edit_parser[] = {
    /* from basicElement */
    {"cursor", set_property_string_value},
    {"dropTarget", set_property_boolean_value},
    {"enabled", set_property_boolean_value},
    {"height", set_property_integer_value},
    {"hitTest", set_property_string_value},
    {"mask", set_property_string_value},
    {"name", set_property_string_value},
    {"offsetHeight", set_property_integer_value},
    {"offsetWidth", set_property_integer_value},
    {"offsetX", set_property_integer_value},
    {"offsetY", set_property_integer_value},
    {"opacity", set_property_integer_value},
    {"pinX", set_property_integer_value},
    {"pinY", set_property_integer_value},
    {"rotation", set_property_float_value},
    {"tagName", set_property_string_value},
    {"tooltip", set_property_string_value},
    {"width", set_property_integer_value},
    {"visible", set_property_boolean_value},
    {"x", set_property_integer_value},
    {"y", set_property_integer_value},
		
    {"background", set_property_string_value},
    {"bold", set_property_boolean_value},
    {"color", set_property_string_value},
    {"font", set_property_string_value},
    {"italic", set_property_boolean_value},
    {"multiline", set_property_boolean_value},
    {"passwordChar", set_property_string_value},
    {"size", set_property_integer_value},
    {"strikeout", set_property_boolean_value},
    {"underline", set_property_boolean_value},
    {"value", set_property_string_value},
    {"wordWrap", set_property_boolean_value},
		
    {ONCLICK, set_property_function_value},
    {ONRCLICK, set_property_function_value},
    {ONDBLCLICK, set_property_function_value},
    {ONRDBLCLICK, set_property_function_value},
    {"ondragdrop", set_property_function_value},
    {"ondragover", set_property_function_value},
    {"onfocusin", set_property_function_value},
    {"onfocusout", set_property_function_value},
    {"onkeydown", set_property_function_value},
    {"onkeypress", set_property_function_value},
    {"onkeyup", set_property_function_value},
    {"onmousedown", set_property_function_value},
    {"onmousemove", set_property_function_value},
    {"onmouseout", set_property_function_value},
    {"onmouseover", set_property_function_value},
    {"onmouseup", set_property_function_value},
    {"onmousewheel", set_property_function_value},		
    {NULL, NULL},
};

static JSBool edit_SetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
    gchar *key;
    desktop_element *element = JS_GetPrivate(cx, obj);
    g_return_val_if_fail(element, JS_FALSE);
    g_return_val_if_fail(JSVAL_IS_STRING(id), JS_FALSE);
    key = JS_GetStringBytes(JSVAL_TO_STRING(id));
    
    if(!element->view)
	return JS_TRUE;

    basicElement_SetProperty(cx,obj,id,vp);

    if(g_ascii_strcasecmp(key, "value") == 0){
	GString *value = g_string_new(NULL);
	if(JSVAL_IS_STRING(*vp)){
	    g_string_append(value, JS_GetStringBytes(JSVAL_TO_STRING(*vp)));
	}else if(JSVAL_IS_INT(*vp)){
	    gint int_value = JSVAL_TO_INT(*vp);
	    g_string_printf(value, "%d", int_value);
	}else if(JSVAL_IS_DOUBLE(*vp)){
	    gdouble double_value;
	    JS_ValueToNumber(cx, *vp, &double_value);
	    g_string_printf(value, "%f", double_value);
	}
	gtk_entry_set_text(GTK_ENTRY(element->view), value->str);
	g_string_free(value, TRUE);
    }

    return JS_TRUE;
}

static JSBool edit_new(JSContext *cx, JSObject *obj, uintN argc, jsval *args, jsval *rval)
{
    return JS_TRUE;
}

JSObject *editClass_init(js_engine *engine, JSObject *parent)
{
    JSObject *proto = NULL;
    proto = JS_InitClass(engine->cx, engine->glob, parent,
			 &editClass, edit_new,
			 0,NULL,NULL,NULL,NULL);
    g_return_val_if_fail(proto, FALSE);
    g_return_val_if_fail(JS_DefineFunctions(engine->cx, proto, edit_methods), FALSE);
    return proto;
}

gboolean edit_onchange(GtkWidget *entry, gpointer ptr)
{
    desktop_element *element = (desktop_element *)ptr;
    JSString *str =JS_NewStringCopyZ(element->engine->cx,gtk_entry_get_text(GTK_ENTRY(entry)));
    jsval val = STRING_TO_JSVAL(str);
    JS_SetProperty(element->engine->cx, element->jsobj, "value", &val);
    desktop_element_call_handler(element, "onchange");
    return FALSE;
}

gboolean edit_focusin(GtkWidget *entry, GdkEventFocus *event, gpointer ptr)
{
    desktop_element *element = (desktop_element *)ptr;
    desktop_element_call_handler(element, "onfocusin");
    return FALSE;
}

void desktop_element_set_view_edit(js_engine *engine, desktop_element *element)
{
    jsval text, width, height;
    gint width_val = -1, height_val = -1;
    element->view = gtk_entry_new();
	
    JS_GetProperty(engine->cx, element->jsobj, "value", &text);
    JS_GetProperty(engine->cx, element->jsobj, "width", &width);
    JS_GetProperty(engine->cx, element->jsobj, "height", &height);
    if(JSVAL_IS_STRING(text)){
	gtk_entry_set_text(GTK_ENTRY(element->view), JS_GetStringBytes(JSVAL_TO_STRING(text)));
    }
    if(JSVAL_IS_INT(width))
	width_val = JSVAL_TO_INT(width);
    if(JSVAL_IS_INT(height))
	height_val = JSVAL_TO_INT(height);
    gtk_widget_set_size_request(element->view, width_val, height_val);
    g_signal_connect(element->view, "button-press-event",
		     G_CALLBACK(edit_focusin), element);
    g_signal_connect(element->view, "changed",
		     G_CALLBACK(edit_onchange), element);
    set_element_event_cb(element);
}
